import { Component, ElementRef, HostListener, ViewChild } from '@angular/core';
import * as THREE from 'three';

@Component({
  selector: 'app-home',
  templateUrl: 'home.page.html',
  styleUrls: ['home.page.scss'],
})
export class HomePage {

  @ViewChild('canvas',  { static: false }) canvasRef: ElementRef;

  private renderer: THREE.WebGLRenderer;
  private camera: THREE.PerspectiveCamera;
  public scene: THREE.Scene;
  public group = new THREE.Group;
  public amount = 5;
  // public group: new THREE.Group();

  public fieldOfView: number = 70;
  public nearClippingPane: number = 0.5;
  public farClippingPane: number = 1000;
  public angle: number = 0;
  
  private lastTime1 = 0; 
  private lastTime2 = 0; 
  private lastTime5 = 0; 
  private lastFrame1 = 0; 
  private lastFrame2 = 0;
  private lastFrame5 = 0;
  private fps1 = 0;
  private fps2 = 0;
  private fps5 = 0;
  private frame = 0;
  private triangleCount = 0;
  private vertexCount = 0;


  constructor() {
    console.log('constructor');
  }

  private get canvas(): HTMLCanvasElement {
    return this.canvasRef.nativeElement;
  }

  /* LIFECYCLE */
  ngAfterViewInit() {
    console.log('ngAfterViewInit');
    this.createScene();
    this.createCamera();
    this.createLight();
    this.startRendering();
  }

  private createScene() {
    this.scene = new THREE.Scene();
    //this.scene.add(new THREE.AxesHelper(200));
    let segments = 128;
    
    var count = Math.pow(this.amount, 3);

    let geometry = new THREE.SphereBufferGeometry(0.4, segments, segments);
    let material = new THREE.MeshPhongMaterial({ color: 0xff0000 });
    // let mesh = new THREE.Mesh(geometry, material);
    // this.scene.add(mesh);
    let i = 0;

    let offset = -(this.amount - 1) / 2;
    // let group = new THREE.Group();
    for (var x = 0; x < this.amount; x++) {
      for (var y = 0; y < this.amount; y++) {
        for (var z = 0; z < this.amount; z++) {
          var newMesh = new THREE.Mesh(geometry, material);
          newMesh.position.set(offset + x, offset + y, offset + z);
          this.group.add(newMesh)
        }
      }
    }
    this.scene.add(this.group)

    this.triangleCount = geometry.index.count /3 * count;

    this.vertexCount = geometry.attributes.position.count * count;

  }

  private createLight() {
    //var light = new THREE.DirectionalLight(0xffffff, 0.8);
    //ight.position.set(100, 100, 100);
    //this.scene.add(light);

    const ambientLight = new THREE.AmbientLight(0x101010);
    this.scene.add(ambientLight);

    const pointLight = new THREE.PointLight(0xffffff, 2, 1000, 1);
    pointLight.position.set(0, 200, 200);
    this.scene.add(pointLight);

    const spotLight = new THREE.SpotLight(0xffffff, 0.5);
    spotLight.position.set(0, 500, 100);
    spotLight.lookAt(this.scene.position);
    this.scene.add(spotLight);
  }

  private createCamera() {
    this.camera = new THREE.PerspectiveCamera(
      this.fieldOfView,
      window.innerWidth / window.innerHeight,
      this.nearClippingPane,
      this.farClippingPane
    );

    // Set position and look at
    //this.camera.position.x = 0;
    //this.camera.position.y = 0;
    //this.camera.position.z = 10;
    this.camera.lookAt(new THREE.Vector3(0, 0, 0));
    this.camera.position.set(0, 0, this.amount * 2);
  }


  private startRendering() {
    // console.log('startRendering');
    this.renderer = new THREE.WebGLRenderer({
      canvas: this.canvas,
      antialias: true
    });

    this.renderer.setClearColor(0x6ad6f0, 1);
    this.renderer.autoClear = true;
    this.renderer.setPixelRatio(devicePixelRatio);
    this.onResize(null);

    this.runRenderLoop();
  }

  public runRenderLoop() {
    requestAnimationFrame(() => this.runRenderLoop());

    var time = Date.now();
    this.frame++;

    let deltaFrame, deltaTime;
    if (this.lastTime1 !== 0) {
        if (time - this.lastTime1 > 1000) {
            deltaFrame = this.frame - this.lastFrame1;
            deltaTime = time - this.lastTime1;
            this.fps1 = Math.round(deltaFrame / deltaTime * 1000);
            this.lastFrame1 = this.frame;
            this.lastTime1 = time;
        }
    } else {
        this.lastTime1 = time;
        this.lastFrame1 = this.frame;
    }

    if (this.lastTime2 !== 0) {
        if (time - this.lastTime2 > 2000) {
            deltaFrame = this.frame - this.lastFrame2;
            deltaTime = time - this.lastTime2;
            this.fps2 = Math.round(deltaFrame / deltaTime * 1000);
            this.lastFrame2 = this.frame;
            this.lastTime2 = time;
        }
    } else {
        this.lastTime2 = time;
        this.lastFrame2 = this.frame;
    }

    if (this.lastTime5 !== 0) {
        if (time - this.lastTime5 > 5000) {
            deltaFrame = this.frame - this.lastFrame5;
            deltaTime = time - this.lastTime5;
            this.fps5 = Math.round(deltaFrame / deltaTime * 1000);
            this.lastFrame5 = this.frame;
            this.lastTime5 = time;
        }
    } else {
        this.lastTime5 = time;
        this.lastFrame5 = this.frame;
    }

    time = time * 0.001;

    this.group.rotation.x = Math.sin(time / 4);
    this.group.rotation.y = Math.sin(time / 2);

    //render scene
    this.renderer.render(this.scene, this.camera);
  }

  @HostListener('window:resize', ['$event'])
  onResize(event) {
    console.log('resize');
    this.canvas.width = window.innerWidth;
    this.canvas.height = window.innerHeight;
    // console.log('render ...');
    this.camera.aspect = window.innerWidth / window.innerHeight;
    this.camera.updateProjectionMatrix();
    this.renderer.setSize(window.innerWidth, window.innerHeight);
  }

}